/**
 * 
 */
package org.proxywars.engine.hud.valuebar;

import java.util.ArrayList;

import com.jme.renderer.ColorRGBA;
import com.jmex.font2d.Text2D;

/**
 * This layer displays all the text on a value bar - min, max, current, percentage, 
 * string, or a range of strings.
 * <p>
 * The plan was to use Text2D to create text labels, but that has fallen through.
 * Haven't really decided how to implement this yet.
 * <p>
 * I am trying to stay away from AWT/Swing as much as possible for speed, 
 * but I am not sure how to handle text bitmaps, or load fonts - in jME2.
 * <p>
 * I might just use some of the examples around from jME1.
 * 
 * @author Steven DeVries
 */
public class ValueBarTextLayer extends ValueBarLayer implements
        InterfaceValueBarTextLayer {

    private static final long serialVersionUID = 1L;
    
    /* Variables */    
    protected ArrayList<ColorRGBA> fontColors;   // Color array used for colorRange.
    protected ArrayList<String> strings;                // string array used for textRange.
    
    protected ArrayList<Text2D> texts;
    
    protected boolean currentIsVisible = true;
    protected boolean maxIsVisible = true;
    protected boolean minIsVisible = false;
    protected boolean percentIsVisible = false;
    protected boolean textIsVisible = false;
    
    protected int currentAlignHorizontal = ALIGN_CENTER;
    protected int currentAlignVertical = ALIGN_CENTER;
    
    protected int maxAlignHorizontal = ALIGN_CENTER;
    protected int maxAlignVertical = ALIGN_CENTER;
    
    protected int minAlignHorizontal = ALIGN_CENTER;
    protected int minAlignVertical = ALIGN_CENTER;
    
    protected int percentAlignHorizontal = ALIGN_CENTER;
    protected int percentAlignVertical = ALIGN_CENTER;
    
    protected int textAlignHorizontal = ALIGN_CENTER;
    protected int textAlignVertical = ALIGN_CENTER;
    
    private int fontSize = 12;
    
    /* Constructors */
    /**
     * Convenience constructor for child classes.
     * Should only ever be used on components that load a skin.
     */
    public ValueBarTextLayer() {
    }

    /**
     * Creates a 125x15 value bar text layer starting at (0,0)
     * with a min of 0 and max 100;
     */
    public ValueBarTextLayer(String name) {
        super(name);
    }

    /**
     * Creates a 125x15 value bar text layer at (0,0) with min and max values set.
     * @param name    Name of the layer.
     * @param min       Minimum value displayed.
     * @param max      Maximum value displayed.
     */
    public ValueBarTextLayer(String name, int min, int max) {
        super(name, min, max);
    }

    /**
     * Creates a value bar text layer at the specified location, height, width, min, and max values.
     * @param name      Name of the layer.
     * @param x           X pixel location of the top left corner.
     * @param y            Y pixel location of top left corner.
     * @param width     Width of the layer.
     * @param height    Height of the layer.
     * @param min        Minimum value displayed.
     * @param max       Maximum value displayed.
     */
    public ValueBarTextLayer(String name, int x, int y, int width, int height,
            int min, int max) {
        super(name, x, y, width, height, min, max);
    }
    
    
    /* Set Methods */
    /**
     * Sets the alignment of all the text in the layer.
     * This has been deprecated since you should manually 
     * set the alignment of each visible element.
     * 
     * @param alignHorizontal    Horizontal alignment constant.
     * @param alignVertical        Vertical alignment constant.
     */
    @Override
    @Deprecated
    public void setAlign(int alignHorizontal, int alignVertical) {
        currentAlignHorizontal = alignHorizontal;
        currentAlignVertical = alignVertical;
        
        maxAlignHorizontal = alignHorizontal;
        maxAlignVertical = alignVertical;
        
        minAlignHorizontal = alignHorizontal;
        minAlignVertical = alignVertical;
        
        percentAlignHorizontal = alignHorizontal;
        percentAlignVertical = alignVertical;
        
        textAlignHorizontal = alignHorizontal;
        textAlignVertical = alignVertical;
        
        // TODO Update Display
    }

    /**
     * Sets the alignment of the text within the ValueBarLayer.
     * Each type of text can be set to a different alignments, 
     * to allow the viewing of all the different values.
     * 
     * @param alignHorizontal - an alignment constant: ALIGN_CENTER, ALIGN_LEFT, ALIGN_RIGHT. 
     * @param alignVertical - an alignment constant: ALIGN_CENTER, ALIGN_BOTTOM, or ALIGN_TOP. 
     * @param type -  a TYPE_* constant: 
     *      TYPE_CURRENT, TYPE_MAX, TYPE_MIN, TYPE_PERCENT, TYPE_TEXT.
     */
    @Override
    public void setAlign(int alignHorizontal, int alignVertical, int type) {
        switch(type) {
        case TYPE_CURRENT:
            currentAlignHorizontal = alignHorizontal;
            currentAlignVertical = alignVertical;
            break;
        case TYPE_MAX:
            maxAlignHorizontal = alignHorizontal;
            maxAlignVertical = alignVertical;
            break;
        case TYPE_MIN:
            minAlignHorizontal = alignHorizontal;
            minAlignVertical = alignVertical;
            break;
        case TYPE_PERCENT:
            percentAlignHorizontal = alignHorizontal;
            percentAlignVertical = alignVertical;
            break;
        case TYPE_TEXT:
            textAlignHorizontal = alignHorizontal;
            textAlignVertical = alignVertical;
            break;            
        }
        
        // TODO Update Display
    }

    /* (non-Javadoc)
     * @see org.proxywars.engine.hud.valuebar.InterfaceValueBarTextLayer#setFont()
     */
    @Override
    public void setFont() {
        // TODO Auto-generated method stub

    }

    /**
     * Sets the color of the font.
     * 
     * @param color color to set the font too.
     */
    @Override
    public void setFontColor(ColorRGBA color) {
        if(     fontColors.isEmpty() || 
                (fontColors.size() ==1 && fontColors.get(0) != color)   ) {
            setColorRange(color, color, 1);
        }
    }

    /**
     * Sets the color range of the font.
     * Using the full/empty colors, the bar generates a color to paint itself with 
     * based on the current value of the bar.
     * 
     * @param emptyColor    color to display when bar is empty.
     * @param fullColor         color to display when bar is full.
     * @param numColors     number of colors between the full and empty color.
     */
    @Override
    public void setFontColorRange(ColorRGBA emptyColor, ColorRGBA fullColor,
            int numColors) {
        ArrayList<ColorRGBA> colorArray = new ArrayList<ColorRGBA>(numColors);
        colorArray.add(fullColor);
        if (numColors >1) {
            colorArray.add(emptyColor);
        }        
        setColorRange(colorArray, numColors);
    }

    /**
     * Sets the color range of the font.  For more information about how color ranges work
     * see the description of setColorRange.
     * 
     * @param colorArray    Array of colors starting with empty color, ending in full color.
     * @param numColors   the number of colors per transition.
     */
    @Override
    public void setFontColorRange(ArrayList<ColorRGBA> colorArray, int numColors) {
        /* Add colors to arrayList */
        if(colorArray.size() == 1) {
            fontColors = colorArray;
        }
        else {
            fontColors = new ArrayList<ColorRGBA>(numColors);            
            
            int numSourceColors = colorArray.size()-1;  // set this way because of how the loop runs
            float colorStep = (1/(float) numColors);
            float rStep, gStep, bStep, aStep;
            float r, g, b, a;
            ColorRGBA currentColor, finalColor;
            
            /* Add first color */
            fontColors.add(colorArray.get(0)    );
            
            /* Transition the color from one to the next and add them to the colors array */
            for(int i=0; i < numSourceColors; i++) {
                currentColor = colorArray.get(i);
                finalColor = colorArray.get(i+1);   // reason size is -1
                
                rStep = (finalColor.r - currentColor.r) * colorStep;
                gStep = (finalColor.g - currentColor.g) * colorStep;
                bStep = (finalColor.b - currentColor.b) * colorStep;
                aStep = (finalColor.a - currentColor.a) * colorStep;
                
                //System.out.println("\nColor Transistion: "+i+", "+currentColor+ " - " +finalColor);                
                for(int j=0; j<numColors; j++) {
                    r = currentColor.r + rStep;
                    g = currentColor.g + gStep;
                    b = currentColor.b + bStep;
                    a = currentColor.a + aStep;
                    
                    //Note: for some reason calling currentColor.set(r, g, b, a) doesn't actually work here.
                    currentColor = new ColorRGBA(r, g, b, a);
                    currentColor.clamp();
                    
                    //System.out.println("Adding Color : " + currentColor);
                    fontColors.add(currentColor);
                }
            }
            
            /*System.out.println("\nReading Color Array:");
            for(int i=0; i < colors.size(); i++) {
                ColorRGBA c = colors.get(i);
                System.out.println("Color "+i+": " + c);
            }*/
        }
        updateFill();
    }

    /**
     * Sets the font size of this layer to jmeUnits, which is essentially 12= 12pt.
     * 
     * @param fontSize      the size of the font.
     */
    @Override
    public void setFontSize(int fontSize) {
        this.fontSize = fontSize;
        
        for(int i=0; i < texts.size(); i++) {
            Text2D temp = texts.get(i);
            temp.setSize(fontSize);
        }
    }

    /* (non-Javadoc)
     * @see org.proxywars.engine.hud.valuebar.InterfaceValueBarTextLayer#setFontStyle(int)
     */
    @Override
    public void setFontStyle(int fontStyle) {
        // TODO Auto-generated method stub

    }

    /**
     * Set the number of places displayed by the bar's percentage.
     * (e.g. 88.07%  or 88%)
     * 
     * @param precision - the number of decimal places.
     */
    @Override
    public void setPrecision(int precision) {
        // TODO Auto-generated method stub

    }

    /**
     * Sets a text string on the bar layer.
     * (e.g. Player or Creature name.)
     * 
     * @param text - A string to be displayed on the bar.
     */
    @Override
    public void setText(String text) {
        strings = new ArrayList<String>(1);
        strings.add(text);
        
        // TODO Update Display

    }

    /**
     * Sets an array of strings for the bar to display.
     * The selected string is based on the value of the bar.
     * (e.g. Healthy, Minor Injuries, Injured, Wounded, Badly Wounded, Dead.)
     * 
     * @param textValues - array of strings to display.
     */
    @Override
    public void setTextRange(ArrayList<String> textValues) {
        strings = new ArrayList<String>(textValues.size());
        for(int i=0; i < strings.size(); i++) {
            strings.add(textValues.get(i) );
        }
        
        // TODO Update Display
    }

    /**
     * Set a type to visible or not, effectively hiding the information on the bar.
     * 
     * @param isVisible - boolean true or false.
     * @param type -  a TYPE_* constant: 
     *      TYPE_CURRENT, TYPE_MAX, TYPE_MIN, TYPE_PERCENT, TYPE_TEXT.  
     */
    @Override
    public void setVisible(boolean isVisible, int type) {        
        switch(type) {
        case TYPE_CURRENT:
            currentIsVisible = isVisible;
            break;
        case TYPE_MAX:
            currentIsVisible = isVisible;
            break;
        case TYPE_MIN:
            currentIsVisible = isVisible;
            break;
        case TYPE_PERCENT:
            currentIsVisible = isVisible;
            break;
        case TYPE_TEXT:
            currentIsVisible = isVisible;
            break;            
        }
        
        // TODO: update display
    }
    
    /**
     * Automatically called when the current value is changed.
     * Updates the value of the current %.
     * It also automatically updates the fill color.
     * 
     * Does not change the size of the bar - since this is a text layer.
     */
    @Override
    protected void updatePercent()
    {
        percent = (((float) (current-min))  /  ((float) (max-min)));
        updateFillColor();
        //setFillSize(percent, percent);
    }
    
    /**
     * Updates the color to fill the bar and text with when using a Color Range.
     */
    @Override
    protected void updateFillColor() {
        super.updateFillColor();
        
        // update the font color
        int numColors = fontColors.size();
        int index = (int) (percent*numColors) -1;
        index = ( ((index < 0) || (numColors == 1)) ? 0 : index);
        ColorRGBA color = colors.get(index);
       
        for(int i=0; i<texts.size(); i++) {
            Text2D temp = texts.get(i);
            temp.setTextColor(color);
        }
    }
    
    protected void updateStrings() {
        
    }

}
